/* 
 * File: mc_threads.cpp
 * Compile: gcc -o mc2 mc_threads.cpp -lpthread 
 * Author: grupo 09
 *
 * Monte Carlo - Versão Paralela
 */

#include <stdio.h>
#include <time.h>
#include <stdlib.h>
#include <pthread.h>

#define MAX 10 // Numero maximo de Threads

int ret;
double dRand(double lower, double upper);
void *monte_carlo(void *n_total);

using namespace std;

int main() {
    pthread_t threads[MAX]; 
    int n = 2147483640/MAX; // numéro de interações, divide as interaçoes por numero de threads
    int *p_in[MAX]; 
    int p_in_sum = 0; // soma total de pontos interno a circuferencia
    int p_total = 0; // pontos total testado
    double result = .0; //para armazena o resultado

    for(int i=0; i<MAX; i++) {
        pthread_create( &(threads[i]), NULL, monte_carlo, &n ); // criação das threads
    }
    
    for(int i=0; i<MAX; i++) {
        pthread_join( threads[i], (void**)&p_in[i] ); // inicia o processo paralelo
    }

    for(int i=0; i<MAX; i++) {
        p_in_sum += (*p_in[i]); // soma todos os valores obtidos de cada Thread
        p_total += n; // soma o valor total
        free(p_in[i]); // libera espaço de memória alocado
    }

    result = ((double)p_in_sum/p_total);  
    result *= 4.0; // realiza a conta do método
 
    printf("%lf\n", result); // imprime o resultado
    return 0;
}


void *monte_carlo( void *n_total ) {
    int i, *p_total = (int*) n_total;

    int *p_in = (int*) malloc (sizeof(int));
    *p_in = 0;

    double px, py;

    srand (time(NULL));
    
    for (i = 0; i < *p_total; i++) {
        // gera um numero aleatorio double  0 entre 1, para cordenada x e y do ponto p
        px = drand48();
        py = drand48();
     
        // verifica se o ponto da dentro, ou fora do 1/4 circulo
        if ( ((px*px)+(py*py))  <= 1.0 ) (*p_in)++;
    }

    // retorna o valor de p_in no join
    pthread_exit( p_in );
    return (void*)p_in;
}
